home *** CD-ROM | disk | FTP | other *** search
/ Windows Game Programming for Dummies (2nd Edition) / WinGamProgFD.iso / pc / DirectX SDK / DXSDK / samples / Multimedia / DirectInput / DIConfig / cdeviceui.cpp < prev    next >
Encoding:
C/C++ Source or Header  |  2001-10-08  |  8.9 KB  |  390 lines

  1. /******************************************************************************
  2.  * File: CDeviceUI.cpp
  3.  *
  4.  * Desc:
  5.  *
  6.  * CDeviceUI is a helper that holds all the views and a bunch of
  7.  * information for a specific device.  It has a CFlexWnd whose
  8.  * handler it sets to the CDeviceView for the current view,
  9.  * thus reusing one window to implement multiple pages.
  10.  *
  11.  * All CDeviceViews and CDeviceControls have a reference to the CDeviceUI
  12.  * that created them (m_ui).  Thus, they also have access to the
  13.  * CUIGlobals, since CDeviceUI has a reference to them (m_ui.m_uig).
  14.  * CDeviceUI also provides the following read-only public variables
  15.  * for convenience, all referring to the device this CDeviceUI
  16.  * represents:
  17.  * 
  18.  * const DIDEVICEINSTANCEW &m_didi;
  19.  * const LPDIRECTINPUTDEVICE8W &m_lpDID;
  20.  * const DIDEVOBJSTRUCT &m_os;
  21.  *
  22.  * See usefuldi.h for a description of DIDEVOBJSTRUCT.
  23.  *
  24.  * CDeviceUI communicates to the rest of the UI via the CDeviceUINotify
  25.  * abstract base class.  Another class (in our case CDIDeviceActionConfigPage)
  26.  * must derive from CDeviceUINotify, and define the DeviceUINotify() and
  27.  * IsControlMapped() virtual functions.  This derived class must be passed as
  28.  * the last parameter to CDeviceUI's Init() function.  All the views and 
  29.  * controls within the views notify the UI of user actions via m_ui.Notify(),
  30.  * so that all actionformat manipulation can be done in the page class.  The
  31.  * views and controls themselves never touch the actionformat.  See the
  32.  * DEVICEUINOTIFY structure below for information on the parameter passed
  33.  * through Notify()/DeviceUINotify().
  34.  *
  35.  * Copyright (C) 1999-2001 Microsoft Corporation. All Rights Reserved.
  36.  *
  37.  ***************************************************************************/
  38.  
  39. #include "common.hpp"
  40. #include <dinputd.h>
  41. #include "configwnd.h"
  42.  
  43. #define DIPROP_MAPFILE MAKEDIPROP(0xFFFD)
  44.  
  45. CDeviceUI::CDeviceUI(CUIGlobals &uig, IDIConfigUIFrameWindow &uif) :
  46.     m_uig(uig), m_UIFrame(uif),
  47.     m_didi(m_priv_didi), m_lpDID(m_priv_lpDID), m_os(m_priv_os),
  48.     m_pCurView(NULL),
  49.     m_pNotify(NULL), m_hWnd(NULL), m_bInEditMode(FALSE)
  50. {
  51.     m_priv_lpDID = NULL;
  52. }
  53.  
  54. CDeviceUI::~CDeviceUI()
  55. {
  56.     Unpopulate();
  57. }
  58.  
  59. HRESULT CDeviceUI::Init(const DIDEVICEINSTANCEW &didi, LPDIRECTINPUTDEVICE8W lpDID, HWND hWnd, CDeviceUINotify *pNotify)
  60. {tracescope(__ts, _T("CDeviceUI::Init()...\n"));
  61.     // save the params
  62.     m_priv_didi = didi;
  63.     m_priv_lpDID = lpDID;
  64.     m_pNotify = pNotify;
  65.     m_hWnd = hWnd;
  66.  
  67.     // fail if we don't have lpDID
  68.     if (m_lpDID == NULL)
  69.     {
  70.         etrace(_T("CDeviceUI::Init() was passed a NULL lpDID!\n"));
  71.         return E_FAIL;
  72.     }
  73.  
  74.     // fill the devobjstruct
  75.     HRESULT hr = FillDIDeviceObjectStruct(m_priv_os, lpDID);
  76.     if (FAILED(hr))
  77.     {
  78.         etrace1(_T("FillDIDeviceObjectStruct() failed, returning 0x%08x\n"), hr);
  79.         return hr;
  80.     }
  81.  
  82.     // view rect needs to be set before populating so the views are
  83.     // created with the correct dimensions
  84.     m_ViewRect = g_ViewRect;
  85.  
  86.     // populate
  87.     hr = PopulateAppropriately(*this);
  88.     if (FAILED(hr))
  89.         return hr;
  90.  
  91.     // if there are no views, return
  92.     if (GetNumViews() < 1)
  93.     {
  94.         Unpopulate();
  95.         return E_FAIL;
  96.     }
  97.  
  98.     // show the first view
  99.     SetView(0);
  100.  
  101.     return hr;
  102. }
  103.  
  104. void CDeviceUI::Unpopulate()
  105. {
  106.     m_pCurView = NULL;
  107.  
  108.     for (int i = 0; i < GetNumViews(); i++)
  109.     {
  110.         if (m_arpView[i] != NULL)
  111.             delete m_arpView[i];
  112.         m_arpView[i] = NULL;
  113.     }
  114.     m_arpView.RemoveAll();
  115.  
  116.     Invalidate();
  117. }
  118.  
  119. void CDeviceUI::SetView(int nView)
  120. {
  121.     if (nView >= 0 && nView < GetNumViews())
  122.         SetView(m_arpView[nView]);
  123. }
  124.  
  125. void CDeviceUI::SetView(CDeviceView *pView)
  126. {
  127.     if (m_pCurView != NULL)
  128.         ShowWindow(m_pCurView->m_hWnd, SW_HIDE);
  129.  
  130.     m_pCurView = pView;
  131.  
  132.     if (m_pCurView != NULL)
  133.         ShowWindow(m_pCurView->m_hWnd, SW_SHOW);
  134. }
  135.  
  136. CDeviceView *CDeviceUI::GetView(int nView)
  137. {
  138.     if (nView >= 0 && nView < GetNumViews())
  139.         return m_arpView[nView];
  140.     else
  141.         return NULL;
  142. }
  143.  
  144. CDeviceView *CDeviceUI::GetCurView()
  145. {
  146.     return m_pCurView;
  147. }
  148.  
  149. int CDeviceUI::GetViewIndex(CDeviceView *pView)
  150. {
  151.     if (GetNumViews() == 0)
  152.         return -1;
  153.  
  154.     for (int i = 0; i < GetNumViews(); i++)
  155.         if (m_arpView[i] == pView)
  156.             return i;
  157.  
  158.     return -1;
  159. }
  160.  
  161. int CDeviceUI::GetCurViewIndex()
  162. {
  163.     return GetViewIndex(m_pCurView);
  164. }
  165.  
  166. // gets the thumbnail for the specified view,
  167. // using the selected version if the view is selected
  168. CBitmap *CDeviceUI::GetViewThumbnail(int nView)
  169. {
  170.     return GetViewThumbnail(nView, GetView(nView) == GetCurView());
  171. }
  172.  
  173. // gets the thumbnail for the specified view,
  174. // specifiying whether or not we want the selected version
  175. CBitmap *CDeviceUI::GetViewThumbnail(int nView, BOOL bSelected)
  176. {
  177.     CDeviceView *pView = GetView(nView);
  178.     if (pView == NULL)
  179.         return NULL;
  180.  
  181.     return pView->GetImage(bSelected ? DVI_SELTHUMB : DVI_THUMB);
  182. }
  183.  
  184. void CDeviceUI::DoForAllControls(DEVCTRLCALLBACK callback, LPVOID pVoid, BOOL bFixed)
  185. {
  186.     int nv = GetNumViews();
  187.     for (int v = 0; v < nv; v++)
  188.     {
  189.         CDeviceView *pView = GetView(v);
  190.         if (pView == NULL)
  191.             continue;
  192.  
  193.         int nc = pView->GetNumControls();
  194.         for (int c = 0; c < nc; c++)
  195.         {
  196.             CDeviceControl *pControl = pView->GetControl(c);
  197.             if (pControl == NULL)
  198.                 continue;
  199.  
  200.             callback(pControl, pVoid, bFixed);
  201.         }
  202.     }
  203. }
  204.  
  205. typedef struct _DFCIAO {
  206.     DWORD dwOffset;
  207.     DEVCTRLCALLBACK callback;
  208.     LPVOID pVoid;
  209. } DFCIAO;
  210.  
  211. void DoForControlIfAtOffset(CDeviceControl *pControl, LPVOID pVoid, BOOL bFixed)
  212. {
  213.     DFCIAO &dfciao = *((DFCIAO *)pVoid);
  214.  
  215.     if (pControl->GetOffset() == dfciao.dwOffset)
  216.         dfciao.callback(pControl, dfciao.pVoid, bFixed);
  217. }
  218.  
  219. void CDeviceUI::DoForAllControlsAtOffset(DWORD dwOffset, DEVCTRLCALLBACK callback, LPVOID pVoid, BOOL bFixed)
  220. {
  221.     DFCIAO dfciao;
  222.     dfciao.dwOffset = dwOffset;
  223.     dfciao.callback = callback;
  224.     dfciao.pVoid = pVoid;
  225.     DoForAllControls(DoForControlIfAtOffset, &dfciao, bFixed);
  226. }
  227.  
  228. void SetControlCaptionTo(CDeviceControl *pControl, LPVOID pVoid, BOOL bFixed)
  229. {
  230.     pControl->SetCaption((LPCTSTR)pVoid, bFixed);
  231. }
  232.  
  233. void CDeviceUI::SetAllControlCaptionsTo(LPCTSTR tszCaption)
  234. {
  235.     DoForAllControls(SetControlCaptionTo, (LPVOID)tszCaption);
  236. }
  237.  
  238. void CDeviceUI::SetCaptionForControlsAtOffset(DWORD dwOffset, LPCTSTR tszCaption, BOOL bFixed)
  239. {
  240.     DoForAllControlsAtOffset(dwOffset, SetControlCaptionTo, (LPVOID)tszCaption, bFixed);
  241. }
  242.  
  243. void CDeviceUI::Invalidate()
  244. {
  245.     if (m_pCurView != NULL)
  246.         m_pCurView->Invalidate();
  247. }
  248.  
  249. void CDeviceUI::SetEditMode(BOOL bEdit)
  250. {
  251.     if (bEdit == m_bInEditMode)
  252.         return;
  253.  
  254.     m_bInEditMode = bEdit;
  255.     Invalidate();
  256. }
  257.  
  258.  
  259. void CDeviceUI::SetDevice(LPDIRECTINPUTDEVICE8W lpDID)
  260. {
  261.     m_priv_lpDID = lpDID;
  262. }
  263.  
  264. BOOL CDeviceUI::IsControlMapped(CDeviceControl *pControl)
  265. {
  266.     if (pControl == NULL || m_pNotify == NULL)
  267.         return FALSE;
  268.  
  269.     return m_pNotify->IsControlMapped(pControl);
  270. }
  271.  
  272. void CDeviceUI::Remove(CDeviceView *pView)
  273. {
  274.     if (pView == NULL)
  275.         return;
  276.  
  277.     int i = GetViewIndex(pView);
  278.     if (i < 0 || i >= GetNumViews())
  279.     {
  280.         assert(0);
  281.         return;
  282.     }
  283.  
  284.     if (pView == m_pCurView)
  285.         m_pCurView = NULL;
  286.  
  287.     if (m_arpView[i] != NULL)
  288.     {
  289.         m_arpView[i]->RemoveAll();
  290.         delete m_arpView[i];
  291.     }
  292.     m_arpView[i] = NULL;
  293.  
  294.     m_arpView.RemoveAt(i);
  295.  
  296.     if (m_arpView.GetSize() < 1)
  297.         RequireAtLeastOneView();
  298.     else if (m_pCurView == NULL)
  299.     {
  300.         SetView(0);
  301.         NumViewsChanged();
  302.     }
  303. }
  304.  
  305. void CDeviceUI::RemoveAll()
  306. {
  307.     m_pCurView = NULL;
  308.  
  309.     for (int i = 0; i < GetNumViews(); i++)
  310.     {
  311.         if (m_arpView[i] != NULL)
  312.             delete m_arpView[i];
  313.         m_arpView[i] = NULL;
  314.     }
  315.     m_arpView.RemoveAll();
  316.  
  317.     RequireAtLeastOneView();
  318. }
  319.  
  320. CDeviceView *CDeviceUI::NewView()
  321. {
  322.     // allocate new view, continuing on if it fails
  323.     CDeviceView *pView = new CDeviceView(*this);
  324.     if (pView == NULL)
  325.         return NULL;
  326.  
  327.     // add view to array
  328.     m_arpView.SetAtGrow(m_arpView.GetSize(), pView);
  329.  
  330.     // create view
  331.     pView->Create(m_hWnd, m_ViewRect, FALSE);
  332.  
  333.     // let the page update to indicate viewness
  334.     NumViewsChanged();
  335.  
  336.     return pView;
  337. }
  338.  
  339. CDeviceView *CDeviceUI::UserNewView()
  340. {
  341.     CDeviceView *pView = NewView();
  342.     if (!pView)
  343.         return NULL;
  344.  
  345.     pView->AddWrappedLineOfText(
  346.         (HFONT)m_uig.GetFont(UIE_PICCUSTOMTEXT),
  347.         m_uig.GetTextColor(UIE_PICCUSTOMTEXT),
  348.         m_uig.GetBkColor(UIE_PICCUSTOMTEXT),
  349.         _T("Customize This View"));
  350.  
  351.     pView->MakeMissingImages();
  352.  
  353.     Invalidate();
  354.  
  355.     return pView;
  356. }
  357.  
  358. void CDeviceUI::RequireAtLeastOneView()
  359. {
  360.     if (GetNumViews() > 0)
  361.         return;
  362.  
  363.     CDeviceView *pView = NewView();
  364.     if (!pView)
  365.         return;
  366.  
  367.     pView->AddWrappedLineOfText(
  368.         (HFONT)m_uig.GetFont(UIE_PICCUSTOMTEXT),
  369.         m_uig.GetTextColor(UIE_PICCUSTOMTEXT),
  370.         m_uig.GetBkColor(UIE_PICCUSTOMTEXT),
  371.         _T("Customize This View"));
  372.     pView->AddWrappedLineOfText(
  373.         (HFONT)m_uig.GetFont(UIE_PICCUSTOM2TEXT),
  374.         m_uig.GetTextColor(UIE_PICCUSTOM2TEXT),
  375.         m_uig.GetBkColor(UIE_PICCUSTOM2TEXT),
  376.         _T("The UI requires at least one view per device"));
  377.  
  378.     pView->MakeMissingImages();
  379.  
  380.     SetView(pView);
  381. }
  382.  
  383. void CDeviceUI::NumViewsChanged()
  384. {
  385.     DEVICEUINOTIFY uin;
  386.     uin.msg = DEVUINM_NUMVIEWSCHANGED;
  387.     Notify(uin);
  388. }
  389.  
  390.